package com.example.service.usr.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.context.PageResult;
import com.example.entity.BaseEntity;
import com.example.entity.UserAddressDO;
import com.example.exception.exception;
import com.example.mapper.UserAddressMapper;
import com.example.service.usr.UserAddressService;
import com.example.vo.addr.AddrResp;
import com.example.vo.addr.UserAddressPageReq;
import com.example.vo.addr.UserAddressReq;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserAddressServiceImpl extends ServiceImpl<UserAddressMapper, UserAddressDO>
        implements UserAddressService {
    @Override
    public PageResult<AddrResp> getAddressList(UserAddressPageReq req) {
        Page<UserAddressDO> page = new Page<>(req.getPage(), req.getSize());
        LambdaQueryWrapper<UserAddressDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserAddressDO::getUid, StpUtil.getLoginIdAsLong());
        wrapper.orderByDesc(UserAddressDO::getIsDefault, BaseEntity::getCreateTime);
        IPage<UserAddressDO> iPage = page(page, wrapper);
        return PageResult.of(iPage.getTotal(), iPage.getCurrent(), iPage.getSize(), iPage.getRecords()
                .stream().map(e -> BeanUtil.toBean(e, AddrResp.class)).toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addAddress(UserAddressReq req) {
        UserAddressDO userAddress = BeanUtil.toBean(req, UserAddressDO.class);
        long uid = StpUtil.getLoginIdAsLong();
        userAddress.setUid(uid);
        LambdaQueryWrapper<UserAddressDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserAddressDO::getUid, uid)
                .eq(UserAddressDO::getIsDefault, true);
        UserAddressDO defaultAddress = getOne(wrapper);
        // 如果没有默认地址，则设置当前地址为默认地址
        if (defaultAddress == null) {
            userAddress.setIsDefault(true);
        } else if (userAddress.getIsDefault()) {
            // 如果有默认地址，则更新原来的默认地址为非默认地址
            defaultAddress.setIsDefault(false);
            if (!updateById(defaultAddress)) {
                throw new exception("设置默认地址失败");
            }
        }
        if (!save(userAddress)) {
            throw new exception("添加失败");
        }
    }

    @Override
    public void updateAddress(UserAddressReq req) {
        UserAddressDO userAddress = BeanUtil.toBean(req, UserAddressDO.class);
        userAddress.setUid(StpUtil.getLoginIdAsLong());
        if (!updateById(userAddress)) {
            throw new exception("修改失败");
        }
    }

    @Override
    public void deleteAddress(Long id) {
        UserAddressDO address = getById(id);
        if (address.getIsDefault()) {
            throw new exception("默认地址不能删除");
        }
        if (!removeById(id)) {
            throw new exception("删除失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setDefault(Long id) {
        UserAddressDO address = getById(id);
        if (!address.getIsDefault()) {
            LambdaQueryWrapper<UserAddressDO> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(UserAddressDO::getUid, StpUtil.getLoginIdAsLong())
                    .eq(UserAddressDO::getIsDefault, true);
            UserAddressDO defaultAddress = getOne(wrapper);
            // 更新现在的地址为默认地址
            address.setIsDefault(true);
            if (!updateById(address)) {
                throw new exception("设置失败");
            }
            // 更新原来的默认地址为非默认地址
            if (defaultAddress != null) {
                defaultAddress.setIsDefault(false);
                if (!updateById(defaultAddress)) {
                    throw new exception("设置失败");
                }
            }
        } else {
            address.setIsDefault(false);
            if (!updateById(address)) {
                throw new exception("设置失败");
            }
        }
    }

    @Override
    public UserAddressDO getAddressById(Long addressId) {
        LambdaQueryWrapper<UserAddressDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserAddressDO::getId, addressId)
                .eq(UserAddressDO::getUid, StpUtil.getLoginIdAsLong());
        return getOne(wrapper);
    }

    @Override
    public AddrResp getDefaultAddress() {
        LambdaQueryWrapper<UserAddressDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserAddressDO::getUid, StpUtil.getLoginIdAsLong())
                .eq(UserAddressDO::getIsDefault, true);
        UserAddressDO address = getOne(wrapper);
        if (address != null) {
            return BeanUtil.toBean(address, AddrResp.class);
        }
        UserAddressDO one = getOne(new LambdaQueryWrapper<UserAddressDO>().eq(UserAddressDO::getUid, StpUtil.getLoginIdAsLong()).last("LIMIT 1"));
        if (one == null) {
            throw new exception("没有默认地址");
        }
        return BeanUtil.toBean(one, AddrResp.class);
    }
}
